<template>
  <el-card>
    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px">
      <div>
        <el-button type="primary" @click="addRoom">添加房间</el-button>
        <el-button type="primary" @click="downloadQRCodes">下载本页二维码</el-button>
      </div>
      <el-input
          v-model="searchRoomNumber"
          @input="handleSearch"
          size="small"
          placeholder="搜索房间号(精确)"
          style="width: 200px"
      />
    </div>

    <el-table :data="rooms" style="width: 100%" border>
      <el-table-column width="100px" label="房间ID" prop="id" />
      <el-table-column label="楼层" prop="floorName" />
      <el-table-column label="类型" prop="typeName" />
      <el-table-column label="二级类型" prop="subType" />

      <el-table-column width="100px" label="房间号" prop="number" />
      <el-table-column width="100px" label="隔间数" prop="cubicleCount" />
      <el-table-column width="100px" label="消耗积分" prop="pointsCost" />
      <el-table-column label="可预约" prop="available" width="70px">
        <template #default="{ row }">
          <el-tag type="success" v-if="row.available">是</el-tag>
          <el-tag type="info" v-else>否</el-tag>
        </template>
      </el-table-column>
      <el-table-column width="300px" label="操作">
        <template #default="scope">
          <el-button size="small" @click="showRoleDialog(scope.row)">分配权限</el-button>
          <el-button size="small" @click="displayQr(scope.row)">二维码</el-button>
          <el-button size="small" @click="editRoom(scope.row)">编辑</el-button>
          <el-button size="small" type="danger" @click="deleteRoom(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-pagination
        v-model:current-page="pageNum"
        v-model:page-size="pageSize"
        :page-sizes="[10, 20, 50, 100]"
        :total="total"
        layout="total, sizes, prev, pager, next"
        @current-change="fetchRooms"
        @size-change="handleSizeChange"
        style="margin-top: 16px; text-align: right"
        background
    />


    <el-dialog v-model="qrDialogVisible" title="隔间签到二维码">
      <QrTable :data="qrData" />
    </el-dialog>

    <el-dialog v-model="dialogVisible" :title="isEdit ? '编辑房间' : '添加房间'">
      <el-form :model="form" ref="formRef" label-width="100px" :rules="rules">
        <div style="max-height: 60vh; overflow-y: auto; padding-right: 10px;">
          <el-form-item label="照片" prop="img">
            <el-upload
                :file-list="imageFileList"
                list-type="picture-card"
                :auto-upload="false"
                :on-change="handleImageChange"
                :on-remove="handleImageRemove"
                :limit="1"
                accept="image/*"
            >
              <el-icon><Plus /></el-icon>
            </el-upload>
          </el-form-item>

          <el-form-item label="楼层" prop="floorId">
            <el-select v-model="form.floorId" placeholder="请选择楼层">
              <el-option v-for="floor in floors" :key="floor.id" :label="floor.name" :value="floor.id" />
            </el-select>
          </el-form-item>

          <el-form-item label="房间号" prop="number">
            <el-input v-model.number="form.number" placeholder="请输入房间号" type="number" />
          </el-form-item>

          <el-form-item label="一级类型" prop="type">
            <el-radio-group v-model="form.type">
              <el-radio value="LAB">实验室</el-radio>
              <el-radio value="MEETING">会议室</el-radio>
            </el-radio-group>
          </el-form-item>

          <el-form-item label="二级类型名称" prop="subType">
            <el-input v-model="form.subType" placeholder="请输入房间名称" />

          </el-form-item>

          <el-form-item label="隔间数量" prop="cubicleCount">
            <el-input v-model.number="form.cubicleCount" placeholder="请输入隔间数量(1-100)" type="number" :disabled="isEdit" />
          </el-form-item>

          <el-form-item label="容量" prop="capacity">
            <el-input v-model.number="form.capacity" placeholder="请输入容量" type="number" />
          </el-form-item>

          <el-form-item label="可被预约">
            <el-switch v-model="form.available" active-text="是" inactive-text="否" />
          </el-form-item>

          <el-form-item label="积分消耗" prop="pointsCost">
            <el-input v-model.number="form.pointsCost" placeholder="请输入积分消耗" type="number" />
          </el-form-item>

          <el-form-item label="开放时间" prop="openTime">
            <el-time-picker
                v-model="form.openTime"
                placeholder="选择开放时间"
                format="HH:mm:ss"
                value-format="HH:mm:ss"
                :default-value="new Date(0, 0, 0, 8, 0, 0)"
            />
          </el-form-item>

          <el-form-item label="关闭时间" prop="closeTime">
            <el-time-picker
                v-model="form.closeTime"
                placeholder="选择关闭时间"
                format="HH:mm:ss"
                value-format="HH:mm:ss"
                :default-value="new Date(0, 0, 0, 20, 0, 0)"
            />
          </el-form-item>
        </div>
      </el-form>

      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitForm">提交</el-button>
      </template>
    </el-dialog>
  </el-card>

  <RoleDialog v-model="roleDialog" :type="type" :resourceIndex="resourceIndex" @close="closeRoleResourceAdd" />
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { getRooms, createRoom, updateRoom, deleteRoomApi } from '@/apps/admin/utils/roomApi'
import { getFloors } from '@/apps/admin/utils/floorApi.js'
import { ElMessage } from 'element-plus'
import QrTable from '@/apps/admin/components/QrTable.vue'
import RoleDialog from '@/apps/admin/components/RoleDialog.vue'
import { Plus } from '@element-plus/icons-vue'
import request from '@/apps/admin/utils/request.js'

const searchRoomNumber = ref('')
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref(0)
const rooms = ref([])
const floors = ref([])
const qrData = ref([])
const qrDialogVisible = ref(false)
const dialogVisible = ref(false)
const imageFileList = ref([])
const isEdit = ref(false)
const currentEditingId = ref(null)
const formRef = ref(null)
const type = ref()
const resourceIndex = ref()
const roleDialog = ref(false)

import QRCode from 'qrcode';
import JSZip from 'jszip';
import { saveAs } from 'file-saver'

const form = ref({
  floorId: null,
  number: null,
  type: '',
  subType: '',
  cubicleCount: null,
  capacity: null,
  available: false,
  pointsCost: null,
  img: null,
  openTime: '',
  closeTime: ''
})

const rules = {
  floorId: [{ required: true, message: '请选择楼层', trigger: 'change' }],
  number: [
    { required: true, message: '请输入房间号', trigger: 'blur' },
    { type: 'number', message: '房间号必须为数字' }
  ],
  type: [{ required: true, message: '请选择一级类型', trigger: 'change' }],
  subType: [{ required: true, message: '请输入二级类型名称', trigger: 'blur' }],
  cubicleCount: [
    { required: true, message: '请输入隔间数量', trigger: 'blur' },
    {
      type: 'number',
      validator: (_, value, cb) => {
        if (value < 1 || value > 100) cb(new Error('隔间数需在 1~100 之间'))
        else cb()
      },
      trigger: 'blur'
    }
  ],
  capacity: [
    { required: true, message: '请输入容量', trigger: 'blur' },
    { type: 'number', message: '容量必须为数字' }
  ],
  pointsCost: [
    { required: true, message: '请输入积分消耗', trigger: 'blur' },
    {
      type: 'number',
      validator: (_, value, cb) => {
        if (value < 0) cb(new Error('积分不能为负数'))
        else cb()
      },
      trigger: 'blur'
    }
  ],
  img: [{ required: true, message: '请上传照片', trigger: 'change' }],
  openTime: [{ required: true, message: '请选择开放时间', trigger: 'change' }],
  closeTime: [{ required: true, message: '请选择关闭时间', trigger: 'change' }]
}

const fetchFloors = async () => {
  const res = await getFloors()
  if (res["code"] === 200) {
    floors.value = res.data
    const map = {}
    res.data.forEach(f => map[f.id] = f.name)
    localStorage.setItem('floorMap', JSON.stringify(map))
  }
}

const fetchRooms = async () => {
  const res = await getRooms({
    page: pageNum.value,
    size: pageSize.value,
    number: searchRoomNumber.value.trim() || undefined
  })
  if (res["code"] === 200) {
    const floorMap = JSON.parse(localStorage.getItem('floorMap') || '{}')
    rooms.value = res.data["records"].map(r => ({
      ...r,
      floorName: floorMap[r.floorId] || '未知楼层'
    }))
    total.value = res.data.total
  }
}

const handleSearch = () => {
  pageNum.value = 1
  fetchRooms()
}

const handleSizeChange = val => {
  pageSize.value = val
  pageNum.value = 1
  fetchRooms()
}

const addRoom = () => {
  dialogVisible.value = true
  isEdit.value = false
  imageFileList.value = []
  currentEditingId.value = null
  form.value = {
    floorId: null,
    number: null,
    type: '',
    subType: '',
    cubicleCount: null,
    capacity: null,
    available: false,
    pointsCost: null,
    img: null,
    openTime: '',
    closeTime: ''
  }
}

const editRoom = (room) => {
  dialogVisible.value = true
  isEdit.value = true
  currentEditingId.value = room.id
  form.value = { ...room, available: !!room.available }
  imageFileList.value = room.img ? [{ name: '房间图片', url: "/api/src/img/" + room.img, value: room.img }] : []
}

const submitForm = () => {
  formRef.value.validate(async (valid) => {
    if (!valid) return
    const payload = { ...form.value, id: currentEditingId.value }
    const res = isEdit.value ? await updateRoom(payload) : await createRoom(payload)
    if (res.code === 200) {
      ElMessage.success(isEdit.value ? '更新成功' : '创建成功')
      dialogVisible.value = false
      await fetchRooms()
    } else {
      ElMessage.error(res.msg || '操作失败')
    }
  })
}

const deleteRoom = async (room) => {
  const res = await deleteRoomApi({ id: room.id })
  if (res.code === 200) {
    ElMessage.success('删除成功')
    await fetchRooms()
  } else {
    ElMessage.error(res.msg || '删除失败')
  }
}

const handleImageChange = async (uploadFile) => {
  const file = uploadFile.raw
  if (file.size > 8 * 1024 * 1024) return ElMessage.error('图片不能超过 8MB')
  const formData = new FormData()
  formData.append('file', file)
  try {
    const res = await request.post('/v1/admin/uploadImg', formData, {
      headers: { 'Content-Type': 'multipart/form-data' }
    })
    form.value.img = res.data.url
    imageFileList.value = [{ name: file.name, url: "/api/src/img/" + res.data.url, value: res.data.url }]
  } catch {
    ElMessage.error('图片上传失败')
  }
}

const handleImageRemove = () => {
  form.value.img = null
  imageFileList.value = []
}

const displayQr = (room) => {
  const floorMap = JSON.parse(localStorage.getItem('floorMap') || '{}')
  qrData.value = Array.from({ length: room.cubicleCount || 1 }, (_, i) => ({
    floorName: floorMap[room.floorId] || '未知楼层',
    roomNumber: room.number,
    cubicleNumber: i + 1,
    content: JSON.stringify({ roomId: room.id, cubicleNumber: i + 1 })
  }))
  qrDialogVisible.value = true
}

const showRoleDialog = (row) => {
  type.value = 'INSTRUMENT'
  resourceIndex.value = row.id
  roleDialog.value = true
}

const closeRoleResourceAdd = () => {
  roleDialog.value = false
}

onMounted(() => {
  fetchFloors()
  fetchRooms()
})

const downloadQRCodes = async () => {
  const zip = new JSZip()

  for (const room of rooms.value) {
    for (let i = 1; i <= room.cubicleCount; i++) {
      let text = JSON.stringify({roomId: room.id, cubicleNumber: i});
      const dataUrl = await QRCode.toDataURL(text, {width: 300})
      const base64 = dataUrl.split(',')[1]
      zip.file(`${room.floorName}_${room.number}_${i}.png`, base64, {base64: true})
    }
  }

  const content = await zip.generateAsync({ type: 'blob' })
  saveAs(content, '房间签到二维码.zip')
}

</script>

<style scoped>
.dialog-footer {
  text-align: right;
}
</style>
